home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr49 / 118_01.zip / TOOLIB1.BDS < prev    next >
Text File  |  1993-06-03  |  14KB  |  706 lines

  1. /* New BDS library for use with software tools
  2.  * source: toolib1.bds
  3.  * version: November 26, 1981
  4.  */
  5.  
  6. #include tools.h
  7.  
  8. /*
  9.    This file contains all the standard BDS C library functions
  10.    which are written in C that are used by the software tools
  11.    programs.
  12.  
  13.    These library functions are identical to the functions
  14.    which were on files stdlib1 and stdlib2.c
  15.    EXCEPT that these functions call some routines whose names
  16.    have changed.
  17.  
  18.    The object code for these functions used to be on deff.crl.
  19.    Now the object code is on toolib1.crl.
  20.  
  21.    The functions on this file ONLY use functions on toolib2.crl
  22.    All the functions with new names are on file toolib2.crl.
  23.    All functions on toolib2.crl came from deff2.crl.
  24.  
  25.    The names have all been changed in the same way,
  26.    viz., by adding a leading underscore character to the
  27.    name.  The following functions have been renamed:
  28.  
  29.    ( * denotes that a call to the function is in this file)
  30.  
  31. _getchar    _ungetch    _putchar *    _putch
  32. _gets *        _call        _read *        _write
  33. _open *        _close *    _creat        (_unlink)
  34. _seek        (_tell)        _rename        _exit
  35. _rread        _rwrite        _rseek        _rtell
  36. _rsrec        _rcfsiz
  37.  
  38.  
  39.    The following functions were on stdlib1.c but
  40.    have been deleted from this file.
  41.  
  42.    getc(), putc(), and ungetc() are now defined on file.bds.
  43.    They had to be completely rewritten to allow for I/O
  44.    redirection.
  45.  
  46. fopen        getc        ungetc        getw
  47. fcreat        putc        putw
  48. fflush        fclose
  49.  
  50. strcat        strcmp        strcpy        strlen
  51. qsort
  52. initw        initb        getval
  53.  
  54.    The following functions from stdlib1.c are on this file:
  55.  
  56. qsort
  57. atoi
  58. isalpha        isupper        islower        isdigit
  59. isspace        toupper        tolower
  60. alloc        free
  61. abs        max        min
  62.  
  63. */
  64.  
  65. /*
  66. This is the new qsort routine, utilizing the shell sort
  67. technique given in the Software Tools book (by Kernighan 
  68. & Plauger.)
  69.  
  70. NOTE: this "qsort" function is different from the "qsort" given
  71. in some old releases (pre 1.32) -- here, the items are sorted
  72. in ASCENDING order.
  73. */
  74.  
  75. qsort(base, nel, width, compar)
  76. char *base; int (*compar)();
  77. {    int gap,ngap, i, j;
  78.     int jd, t1, t2;
  79.     t1 = nel * width;
  80.     for (ngap = nel / 2; ngap > 0; ngap /= 2) {
  81.        gap = ngap * width;
  82.        t2 = gap + width;
  83.        jd = base + gap;
  84.        for (i = t2; i <= t1; i += width)
  85.           for (j =  i - t2; j >= 0; j -= gap) {
  86.         if ((*compar)(base+j, jd+j) <=0) break;
  87.              _swp(width, base+j, jd+j);
  88.           }
  89.     }
  90. }
  91.  
  92. _swp(w,a,b)
  93. char *a,*b;
  94. int w;
  95. {
  96.     char tmp;
  97.     while(w--) {tmp=*a; *a++=*b; *b++=tmp;}
  98. }
  99.  
  100.  
  101. /*
  102.     Some string functions
  103. */
  104.  
  105. int atoi(n)
  106. char *n;
  107. {
  108.     int val; 
  109.     char c;
  110.     int sign;
  111.     val=0;
  112.     sign=1;
  113.     while ((c = *n) == '\t' || c== ' ') ++n;
  114.     if (c== '-') {sign = -1; n++;}
  115.     while (  isdigit(c = *n++)) val = val * 10 + c - '0';
  116.     return sign*val;
  117. }
  118.  
  119.  
  120. /*
  121.     Some character diddling functions
  122. */
  123.  
  124. int isalpha(c)
  125. char c;
  126. {
  127.     return isupper(c) || islower(c);
  128. }
  129.  
  130.  
  131. int isupper(c)
  132. char c;
  133. {
  134.     return c>='A' && c<='Z';
  135. }
  136.  
  137.  
  138. int islower(c)
  139. char c;
  140. {
  141.     return c>='a' && c<='z';
  142. }
  143.  
  144.  
  145. int isdigit(c)
  146. char c;
  147. {
  148.     return c>='0' && c<='9';
  149. }
  150.  
  151.  
  152. int isspace(c)
  153. char c;
  154. {
  155.     return c==' ' || c=='\t' || c=='\n';
  156. }
  157.  
  158.  
  159. char toupper(c)
  160. char c;
  161. {
  162.     return islower(c) ? c-32 : c;
  163. }
  164.  
  165.  
  166. char tolower(c)
  167. char c;
  168. {
  169.     return isupper(c) ? c+32 : c;
  170. }
  171.  
  172.  
  173. /*
  174. Storage allocation routines, taken from chapter 8 of K&R, but
  175. simplified to ignore the storage allignment problem and not
  176. bother with the "morecore" hack (a call to "sbrk" under CP/M is
  177. a relatively CHEAP operation, and can be done on every call to
  178. "alloc" without degrading efficiency.)
  179. */
  180.  
  181. char *alloc(nbytes)
  182. unsigned nbytes;
  183. {
  184.     struct _header *p, *q, *cp;
  185.     int nunits; 
  186.  
  187.     /* comment out -----
  188.     printf("In alloc: nbytes = %d\n", nbytes);
  189.     ----- end comment out */
  190.  
  191.     nunits = 1 + (nbytes + (sizeof (_base) - 1)) / sizeof (_base);
  192.     if ((q = _allocp) == NULL) {
  193.         _base._ptr = _allocp = q = &_base;
  194.         _base._size = 0;
  195.      }
  196.     for (p = q -> _ptr; ; q = p, p = p -> _ptr) {
  197.         if (p -> _size >= nunits) {
  198.             if (p -> _size == nunits)
  199.                 q -> _ptr = p -> _ptr;
  200.             else {
  201.                 p -> _size -= nunits;
  202.                 p += p -> _size;
  203.                 p -> _size = nunits;
  204.              }
  205.             _allocp = q;
  206.  
  207.             /* comment out -----
  208.             printf("Alloc returns: %x\n", p+1);
  209.             ----- end comment out */
  210.  
  211.             return p + 1;
  212.         }
  213.         if (p == _allocp) {
  214.             cp = sbrk(nunits * sizeof (_base));
  215.             if (cp == ERROR) {
  216.                 printf("Alloc: Out of memory");
  217.                 return NULL;
  218.             }
  219.             cp -> _size = nunits; 
  220.             /* remember:  pointer arithmetic ! */
  221.             free(cp+1);    
  222.             p = _allocp;
  223.         }
  224.     }
  225. }
  226.  
  227.  
  228. free(ap)
  229. struct _header *ap;
  230. {
  231.     struct _header *p, *q;
  232.  
  233.     /* comment out -----
  234.     printf("In free:  ap = %x\n", ap);
  235.     ----- end comment out */
  236.  
  237.     p = ap - 1;    /* No need for the cast when "ap" is a struct ptr */
  238.  
  239.     for (q = _allocp; !(p > q && p < q -> _ptr); q = q -> _ptr)
  240.         if (q >= q -> _ptr && (p > q || p < q -> _ptr))
  241.             break;
  242.     if (p + p -> _size == q -> _ptr) {
  243.         p -> _size += q -> _ptr -> _size;
  244.         p -> _ptr = q -> _ptr -> _ptr;
  245.      }
  246.     else p -> _ptr = q -> _ptr;
  247.  
  248.     if (q + q -> _size == p) {
  249.         q -> _size += p -> _size;
  250.         q -> _ptr = p -> _ptr;
  251.      }
  252.     else q -> _ptr = p;
  253.  
  254.     _allocp = q;
  255.  
  256.     /* comment out -----
  257.     printf("In free:  new _allocp = %x\n", q);
  258.     ----- end comment out */
  259.  
  260. }
  261.  
  262.  
  263. /*
  264.     define max(), min(), abs()
  265. */
  266.  
  267. int abs(n)
  268. {
  269.     return (n<0) ? -n : n;
  270. }
  271.  
  272. int max(a,b)
  273. {
  274.     return (a > b) ? a : b;
  275. }
  276.  
  277. int min(a,b)
  278. {
  279.     return (a <= b) ? a : b;
  280. }
  281.  
  282.  
  283.  
  284. /*
  285.    The following functions from stdlib2.c are on this file:
  286.  
  287.     printf        _spr 
  288.     scanf        _scn
  289.     _puts  (renamed by analogy to _get)
  290.     swapin
  291.  
  292.     The following functions from stdlib2 have been deleted:
  293.  
  294.     fprintf        sprintf
  295.     scanf        sscanf
  296.     fputs        fgets
  297.  
  298.  
  299.     Many comments have been deleted from these functions.
  300.     See STDLIB2.C if you are really interested.
  301.  
  302.     Each function uses an array of dimension MAXLINE.
  303.     Make sure MAXLINE is longer than the largest line
  304.     ever printed!
  305.  
  306.     Remember to put out a 0x1a (control-Z, CPMEOF) at
  307.     the end of text files being written out to disk.
  308.  
  309.     Also remember that there are two end of file
  310.     conditions:  -1 and CPMEOF.
  311. */
  312.  
  313.  
  314. /*
  315.     printf
  316.  
  317.     usage:
  318.         printf(format, arg1, arg2, ...);
  319.     
  320.     Exactly the same as in Kernighan & Ritchie.
  321. */
  322.  
  323. printf(format)
  324. char *format;
  325. {
  326.     char line[MAXLINE];
  327.  
  328.     _spr(line,&format);    /* use "_spr" to form the output */
  329.  
  330.     /* comment out -----
  331.     _puts(line);        /* and print out the line     */
  332.     ----- end comment out */
  333.     putlin(line, STDOUT);
  334. }
  335.  
  336.  
  337. /*
  338.     scanf:
  339.     This one accepts a line of input text from the
  340.     console, and converts the text to the required
  341.     binary or alphanumeric form. (see K & R)
  342.  
  343.     Usage:
  344.         scanf(format, ptr1, ptr2, ...);
  345.  
  346.     Returns number of items matched.
  347.  
  348.     Since a new line of text must be entered from the
  349.     console each time scanf is called, any unprocessed
  350.     text left over from the last call is lost forever.
  351.     This is a difference between BDS  and UNIX.
  352.  
  353.     The field width specification is not supported.
  354. */
  355.  
  356. int scanf(format)
  357. char *format;
  358. {
  359.     char line[MAXLINE];
  360.  
  361.     /* comment out -----
  362.     _gets(line);    /* get a line of input from user */
  363.     ----- end comment out */
  364.     getlin(line, STDIN);
  365.  
  366.     return _scn(line,&format);    /* and scan it with "_scn"     */
  367. }
  368.  
  369.  
  370. /*
  371.     sprintf:
  372.     Like fprintf, except a string pointer is specified
  373.     instead of a buffer pointer. The text is written
  374.     directly into memory where the string pointer points.
  375.  
  376.     Usage:
  377.         sprintf(string,format,arg1, arg2, ...);
  378. */
  379.  
  380. sprintf(buffer,format)
  381. char *buffer, *format;
  382. {
  383.     _spr(buffer,&format);    /* call _spr to do all the work */
  384. }
  385.  
  386.  
  387. /*
  388.     sscanf:
  389.  
  390.     Reads a line of text in from the console and scans it
  391.     for variable values specified in the format string.
  392.     See the comments below in _scn()
  393.  
  394.     Usage:
  395.         sscanf(format,&arg1,&arg2,...);
  396. */
  397.  
  398. int sscanf(line,format)
  399. char *line, *format;
  400. {
  401.     return _scn(line,&format);    /* let _scn do all the work */
  402. }
  403.  
  404.  
  405.  
  406. /*
  407.     General formatted output conversion routine, used by
  408.     fprintf and sprintf..."line" is where the output is
  409.     written, and "fmt" is a pointer to an argument list 
  410.     which must consist of a format string pointer and
  411.     subsequent list of (optional) values.
  412.  
  413.     The arguments are, of course, passed on the stack.
  414. */
  415.  
  416.  
  417. _spr(line,fmt)
  418. char *line, **fmt;
  419. {
  420.     char _uspr(), c, base, *sptr, *format;
  421.     char wbuf[MAXLINE], *wptr, pf, ljflag, zfflag;
  422.     int width, precision,  *args;
  423.  
  424.     format = *fmt++;    /* fmt first points to the format string    */
  425.     args = fmt;        /* now fmt points to the first arg value    */
  426.  
  427.     while (c = *format++)
  428.       if (c == '%') {
  429.         wptr = wbuf;
  430.         precision = 6;
  431.         ljflag = pf = zfflag = 0;
  432.  
  433.         if (*format == '-') {
  434.             format++;
  435.             ljflag++;
  436.          }
  437.  
  438.  
  439.         if (*format == '0') zfflag++;    /* zero-fill feature test */
  440.  
  441.         width = (isdigit(*format)) ? _gv2(&format) : 1;
  442.  
  443.         if ((c = *format++) == '.') {
  444.             precision = _gv2(&format);
  445.             pf++;
  446.             c = *format++;
  447.          }
  448.  
  449.         switch(toupper(c)) {
  450.  
  451.         case 'D':  if (*args < 0) {
  452.                 *wptr++ = '-';
  453.                 *args = -*args;
  454.                 width--;
  455.                 }
  456.  
  457.         case 'U':  base = 10; goto val;
  458.  
  459.         case 'X':  base = 16; goto val;
  460.  
  461.         case 'O':  base = 8;  /* note that arbitrary bases can be
  462.                          added easily before this line */
  463.  
  464.              val:  width -= _uspr(&wptr,*args++,base);
  465.                goto pad;
  466.  
  467.         case 'C':  *wptr++ = *args++;
  468.                width--;
  469.                goto pad;
  470.  
  471.         case 'S':  if (!pf) precision = 200;
  472.                sptr = *args++;
  473.                while (*sptr && precision) {
  474.                 *wptr++ = *sptr++;
  475.                 precision--;
  476.                 width--;
  477.                 }
  478.  
  479.              pad:  *wptr = '\0';
  480.              pad2: wptr = wbuf;
  481.                if (!ljflag)
  482.                 while (width-- > 0)
  483.                     *line++ = zfflag ? '0' : ' ';
  484.  
  485.                while (*line = *wptr++)
  486.                 line++;
  487.  
  488.                if (ljflag)
  489.                 while (width-- > 0)
  490.                     *line++ = ' ';
  491.                break;
  492.  
  493.          default:  *line++ = c;
  494.  
  495.          }
  496.       }
  497.       else *line++ = c;
  498.  
  499.     *line = '\0';
  500. }
  501.  
  502. /*
  503.     Internal routine used by "_spr" to perform ascii-
  504.     to-decimal conversion and update an associated pointer:
  505. */
  506.  
  507. int _gv2(sptr)
  508. char **sptr;
  509. {
  510.     int n;
  511.     n = 0;
  512.     while (isdigit(**sptr)) n = 10 * n + *(*sptr)++ - '0';
  513.     return n;
  514. }
  515.  
  516.  
  517. /*
  518.     Internal function which converts n into an ASCII
  519.     base `base' representation and places the text
  520.     at the location pointed to by the pointer pointed
  521.     to by `string'. Yes, you read that correctly.
  522. */
  523.  
  524. char _uspr(string, n, base)
  525. char **string;
  526. unsigned n;
  527. {
  528.     char length;
  529.     if (n<base) {
  530.         *(*string)++ = (n < 10) ? n + '0' : n + 55;
  531.         return 1;
  532.     }
  533.     length = _uspr(string, n/base, base);
  534.     _uspr(string, n%base, base);
  535.     return length + 1;
  536. }
  537.  
  538.  
  539. /*
  540.     General formatted input conversion routine. "line" points
  541.     to a string containing ascii text to be converted, and "fmt"
  542.     points to an argument list consisting of first a format
  543.     string and then a list of pointers to the destination objects.
  544.  
  545.     Appropriate data is picked up from the text string and stored
  546.     where the pointer arguments point according to the format string.
  547.     See K&R for more info.
  548.  
  549.     The field width specification is not supported.
  550.  
  551.     NOTE: the "%s" termination character has been changed
  552.     from "any white space" to the character following the
  553.     the %s specification in the format string.
  554.     That is, the call
  555.  
  556.         sscanf(string, "%s:", &str);
  557.  
  558.     would ignore leading white space (as is the case with
  559.     all format conversions), and then read in ALL following
  560.     text (including newlines) into the buffer "str"
  561.     until a COLON or null byte is encountered.
  562.  
  563. */
  564.  
  565. int _scn(line,fmt)
  566. char *line, **fmt;
  567. {
  568.     char sf, c, base, n, *sptr, *format;
  569.     int sign, val, **args;
  570.  
  571.     format = *fmt++;    /* fmt first points to the format string */
  572.     args = fmt;        /* now it points to the arg list */
  573.  
  574.     n = 0;
  575.     while (c = *format++) {
  576.        if (!*line) return n;    /* if end of input string, return */
  577.        if (isspace(c)) continue;    /* skip white space in format string */
  578.        if (c != '%') {        /* if not %, must match text */
  579.         if (c != _igs(&line)) return n;
  580.         else line++;
  581.         }
  582.        else {            /* process conversion */
  583.         sign = 1;
  584.         base = 10;
  585.         sf = 0;
  586.         if ((c = *format++) == '*') {
  587.             sf++;        /* if "*" given, supress assignment */
  588.             c = *format++;
  589.          }
  590.         switch (toupper(c)) {
  591.            case 'X': base = 16;
  592.                  goto doval;
  593.  
  594.            case 'O': base = 8;
  595.                  goto doval;
  596.  
  597.            case 'D': if (_igs(&line) == '-') {
  598.                 sign = -1;
  599.                 line++;
  600.                   }
  601.  
  602.        doval:  case 'U': val = 0;
  603.                  if (_bc(_igs(&line),base) == ERROR)
  604.                 return n;
  605.                  while ((c = _bc(*line++,base)) != 255)
  606.                 val = val * base + c;
  607.                  line--;
  608.                  break;
  609.  
  610.            case 'S': _igs(&line);
  611.                  sptr = *args;
  612.                  while (c = *line++)   {
  613.                 if (c == *format) {
  614.                     format++;
  615.                     break;
  616.                  }
  617.                 if (!sf) *sptr++ = c;
  618.                   }                
  619.                  if (!sf) {
  620.                 n++;
  621.                 *sptr = '\0';
  622.                 args++;
  623.                   }
  624.                  continue;
  625.  
  626.            case 'C': if (!sf) {
  627.                 poke(*args++, *line);
  628.                 n++;
  629.                  }
  630.                  line++;
  631.                  continue;
  632.  
  633.            default:  return n;
  634.          }
  635.         if (!sf) {
  636.             **args++ = val * sign;
  637.             n++;
  638.          }
  639.     }}
  640.     return n;
  641. }
  642.  
  643. /*
  644.     Internal function to position the character
  645.     pointer argument to the next non white-space
  646.     character in the string:
  647. */
  648.  
  649. char _igs(sptr)
  650. char **sptr;
  651. {
  652.     char c;
  653.     while (isspace(c = **sptr)) ++*sptr;
  654.     return (c);
  655. }
  656.  
  657.  
  658. /*
  659.     Internal function to convert character c to value
  660.     in base b , or return ERROR if illegal character for that
  661.     base:
  662. */
  663.  
  664. int _bc(c,b)
  665. char c,b;
  666. {
  667.     if (isalpha(c = toupper(c))) c -= 55;
  668.          else  if (isdigit(c))  c -= 0x30;
  669.      else return ERROR;
  670.     if (c > b-1) return ERROR;
  671.         else return c;
  672. }
  673.  
  674.  
  675. /*
  676.     _puts:
  677.     Write out the given string to the console.
  678.     A newline is NOT automatically appended:
  679. */
  680.  
  681. _puts(s)
  682. char *s;
  683. {
  684.     while (*s) _putchar(*s++);
  685. }
  686.  
  687.  
  688. swapin(name,addr)
  689. char *name;        /* the file to swap in */
  690. {
  691.     int fd;
  692.     if (( fd = _open(name,0)) == ERROR) {
  693.         printf("Swapin: cannot open %s\n",name);
  694.         return ERROR;
  695.     }
  696.     if ((_read(fd,addr,512)) < 0) {
  697.         printf("Swapin: read error on %s\n",name);
  698.         _close(fd);
  699.         return ERROR;
  700.     }
  701.     _close(fd);
  702.     return OK;
  703. }
  704.  
  705.  
  706.